package com.junxonline.instant.admin.service.config.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.junxonline.instant.dao.entity.dto.common.RolePermissionInfoDTO;
import com.junxonline.instant.dao.entity.dto.ui.SelectNodeDTO;
import com.junxonline.instant.dao.entity.model.config.*;
import com.junxonline.instant.dao.entity.vo.config.PermissionVO;
import com.junxonline.instant.dao.entity.vo.config.RoleVO;
import com.junxonline.instant.dao.mapper.config.RoleMapper;
import com.junxonline.instant.dao.mapper.config.RoleMenuMapper;
import com.junxonline.instant.dao.mapper.config.RoleOrganizationMapper;
import com.junxonline.instant.admin.service.config.RoleService;
import com.junxonline.instant.common.annotation.DataScope;
import com.junxonline.instant.common.entity.common.CommonReqPage;
import com.junxonline.instant.common.entity.common.CommonRespPage;
import com.junxonline.instant.common.enumeration.AdminErrorEnum;
import com.junxonline.instant.common.enumeration.DataScopeEnum;
import com.junxonline.instant.common.exception.AdminBizException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 角色管理接口实现类
 *
 * @author JunX
 * @date 2021-06-24
 */
@Service
@Transactional
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleMenuMapper roleMenuMapper;

    @Autowired
    private RoleOrganizationMapper roleOrganizationMapper;

    /**
     * 查询角色列表（Select）
     *
     * @param wrapper 条件查询器
     * @return List<SelectNodeDTO>
     */
    @Override
    @DataScope
    public List<SelectNodeDTO> queryRoleList(Wrapper<Role> wrapper) {
        List<SelectNodeDTO> roles = new ArrayList<>();
        List<Role> roleList = roleMapper.queryRoleList(wrapper);
        for (Role role : roleList) {
            roles.add(new SelectNodeDTO(role.getId(), role.getId().toString(), "[" + role.getOrganizationName() + "]" + role.getName()));
        }
        return roles;
    }

    /**
     * 查询角色列表
     *
     * @param vo      请求参数
     * @param wrapper 条件查询器
     * @return CommonRespPage<Role>
     */
    @Override
    @DataScope
    public CommonRespPage<Role> queryList(CommonReqPage<RoleVO> vo, QueryWrapper<Role> wrapper) {
        wrapper.like(StrUtil.isNotBlank(vo.getQueryParams().getName()), "t.name", vo.getQueryParams().getName());
        wrapper.eq(vo.getQueryParams().getStatus() != null, "t.status", vo.getQueryParams().getStatus());
        wrapper.eq(vo.getQueryParams().getDataScope() != null, "t.data_scope", vo.getQueryParams().getDataScope());
        wrapper.in(vo.getQueryParams().getOrganizationId() != null, "t.organization_id", vo.getQueryParams().getOrganizationId());
        return CommonRespPage.success(roleMapper.queryList(new Page<>(vo.getPage(), vo.getPageSize()), wrapper));
    }

    /**
     * 查询角色
     *
     * @param id ID
     * @return Role
     */
    @Override
    public Role query(Long id) {
        Role role = roleMapper.selectById(id);
        Assert.notNull(role, AdminErrorEnum.DATA_IS_NOT_EXISTS.getMsg());
        return role;
    }

    /**
     * 新增角色
     *
     * @param role 请求参数
     */
    @Override
    public void add(Role role) {
        Integer count = roleMapper.selectCount(new LambdaQueryWrapper<Role>()
                .eq(Role::getOrganizationId, role.getOrganizationId())
                .eq(Role::getName, role.getName()));
        if (count > 0) {
            throw new AdminBizException(AdminErrorEnum.DATA_IS_EXISTS);
        }
        role.setDataScope(DataScopeEnum.ORGANIZATION_AND_CHILD.getValue());
        roleMapper.insert(role);
    }

    /**
     * 编辑角色
     *
     * @param role 请求参数
     */
    @Override
    public void edit(Role role) {
        Integer count = roleMapper.selectCount(new LambdaQueryWrapper<Role>()
                .ne(Role::getId, role.getId())
                .eq(Role::getOrganizationId, role.getOrganizationId())
                .eq(Role::getName, role.getName()));
        if (count > 0) {
            throw new AdminBizException(AdminErrorEnum.DATA_IS_EXISTS);
        }
        roleMapper.updateById(role);
    }

    /**
     * 删除角色
     *
     * @param ids 请求参数
     */
    @Override
    public void delete(List<Long> ids) {
        roleMapper.deleteBatchIds(ids);
        for (Long roleId : ids) {
            roleMenuMapper.delete(new LambdaUpdateWrapper<RoleMenu>().eq(RoleMenu::getRoleId, roleId));
        }
    }

    /**
     * 查询角色权限
     *
     * @param vo 请求参数
     * @return RolePermissionInfoDTO
     */
    @Override
    public RolePermissionInfoDTO queryRolePermission(RoleVO vo) {
        RolePermissionInfoDTO dto = new RolePermissionInfoDTO();
        // 菜单权限
        List<RoleMenu> roleMenus = roleMenuMapper.selectList(new LambdaQueryWrapper<RoleMenu>().eq(RoleMenu::getRoleId, vo.getId()));
        List<String> menuIds = new ArrayList<>();
        for (RoleMenu roleMenu : roleMenus) {
            menuIds.add(String.valueOf(roleMenu.getMenuId()));
        }
        dto.setMenuIds(menuIds);
        // 数据权限类型
        Role role = roleMapper.selectById(vo.getId());
        dto.setDataScope(String.valueOf(role.getDataScope()));
        // 数据权限
        List<RoleOrganization> roleOrganizations = roleOrganizationMapper.selectList(new LambdaQueryWrapper<RoleOrganization>().eq(RoleOrganization::getRoleId, vo.getId()));
        List<String> dataIds = new ArrayList<>();
        for (RoleOrganization roleOrganization : roleOrganizations) {
            dataIds.add(String.valueOf(roleOrganization.getOrganizationId()));
        }
        dto.setDataIds(dataIds);
        return dto;
    }

    /**
     * 设置权限
     *
     * @param vo 请求参数
     */
    @Override
    public void setPermission(PermissionVO vo) {
        // 清空角色菜单权限
        Long roleId = vo.getId();
        roleMenuMapper.delete(new LambdaUpdateWrapper<RoleMenu>().eq(RoleMenu::getRoleId, roleId));
        // 设置角色菜单权限
        if (vo.getMenuIds() != null) {
            for (Long menuId : vo.getMenuIds()) {
                roleMenuMapper.insert(new RoleMenu(roleId, menuId));
            }
        }
        // 设置角色数据权限类型
        if (vo.getDataScope() != null) {
            Role role = roleMapper.selectById(roleId);
            if (role != null) {
                role.setDataScope(vo.getDataScope());
                roleMapper.updateById(role);
            }
            // 清空角色数据权限
            roleOrganizationMapper.delete(new LambdaQueryWrapper<RoleOrganization>().eq(RoleOrganization::getRoleId, roleId));
            // 如果类型是自定义数据权限
            if (vo.getDataScope().equals(DataScopeEnum.CUSTOM.getValue())) {
                // 设置角色数据权限
                if (vo.getDataIds() != null) {
                    for (Long organizationId : vo.getDataIds()) {
                        roleOrganizationMapper.insert(new RoleOrganization(roleId, organizationId));
                    }
                }
            }
        }
    }

}
